﻿#include "Matrix.h"
#include "Constant.h"
#include "CoordSys.h"
#include "TimeSys.h"
#include "ReadN.h"
#include "ReadO.h"
#include "GNSSSatPos.h"
#include "IonoCorr.h"
#include "TropCorr.h"
#include "Spp.h"
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdlib>
using namespace std;

/* 主函数：测试各类功能 */
int main() {
    /* 测试常数类 */
    GNSSconsts* pGnssConst;
    BDSConsts bdsConst;
    pGnssConst = &bdsConst;  // 基类指针指向派生类对象
    cout << fixed << pGnssConst->get_refEllip().f << endl;

    /* 测试矩阵类 */
    cout << "/* 测试矩阵类 */" << endl;
    Matrix matTest;
    matTest.test();  // 执行矩阵类自测试

    /* 测试坐标系统类 */
    cout << "/* 测试坐标系统类 */" << endl;
    CoordSys* pCoordSys;
    BDCS bdcs(bdsConst.get_refEllip());  // 创建BDCS坐标系
    pCoordSys = &bdcs;
    pCoordSys->test();  // 执行坐标系统自测试

    /* 测试时间系统类 */
    cout << "/* 测试时间系统类 */" << endl;
    CalendT t = { 2016,7,14,1,0,0 };  // 测试时间
    BDSTime mBDST;  // 北斗时间系统
    TimeSys* pTimeSys = &mBDST;
    pTimeSys->print_time(t);  // 打印日历时间
    cout << " 对应的BDS时间为：" << endl;
    SOW t2 = pTimeSys->calend2sow(t);  // 转换为周内秒
    pTimeSys->print_time(t2);  // 打印周内秒时间

    /* 测试 Read N 文件类 */
    ReadN mReadN("rinex302N.txt");  // 创建星历文件读取器
    if (!mReadN.parseFile()) return false;  // 解析文件
    if (!mReadN.print_eph()) return false;  // 打印星历数据

    /* 测试 Read O 文件类 */
    string filename = "rinex302O.txt";  // 观测数据文件
    ReadO mReadO(filename);  // 创建观测文件读取器
    if (!mReadO.parse_file()) return false;  // 解析文件
    mReadO.print_head();  // 打印文件头
    mReadO.print_body(2);  // 打印前2个历元的观测数据
    vector<obsEpoch>* mObs = mReadO.get_obs();  // 获取观测数据
    BaseT tr = pTimeSys->str2baseT(mObs->at(0).time);  // 转换首个历元时间

    /* 测试卫星位置计算类 */
    cout << "/* 卫星位置计算类 */" << endl;
    GNSSSatPos* pSatPos;
    BDSSatPos mBDSSatPos(pTimeSys, &mReadN);  // 北斗卫星位置计算器
    pSatPos = &mBDSSatPos;
    XYZ ps1 = pSatPos->get_satPos("C01", tr);  // 计算C01卫星位置
    printf("C01 卫星位置：X=%.3f m, Y=%.3f m, Z=%.3f m\n\n", ps1.x, ps1.y, ps1.z);

    /* 电离层延迟误差改正 */
    cout << "/*电离层延迟误差改正类 */" << endl;
    IonoCorr mIonCor(pGnssConst, &mReadN.get_head());  // 电离层改正器
    CalendT tObs = { 2017, 3, 7, 5, 6, 35, 0.00 };  // 测试时间
    SOW sow = pTimeSys->calend2sow(tObs);  // 转换为周内秒

    XYZ rr = { -2091342.6543,4800418.4462,3629758.3665 };  // 接收机近似位置
    BLH blh = pCoordSys->XYZ2BLH(rr);  // 转换为大地坐标
    Azel azel = pCoordSys->get_azel(rr, ps1);  // 计算高度角/方位角
    double ionCor = mIonCor.get_ionoCorr(blh, azel, sow);  // 计算电离层延迟
    cout << fixed << ionCor << endl << endl;

    /* 对流层延迟误差改正 */
    cout << "/*对流层延迟误差改正类 */" << endl;
    TropCorr mTropCor(pGnssConst);  // 对流层改正器
    double tropCor = mTropCor.get_tropCorr(blh, azel.ele);  // 计算对流层延迟
    cout << fixed << tropCor << endl << endl;

    /* 单点定位全过程 */
    // 创建单点定位处理器
    Spp spp(&bdcs, &mBDSSatPos, &mIonCor, &mTropCor, &mReadO, &mReadN, pTimeSys);

    // 设置初始位置（设为原点）
    XYZ rxPos = { 0, 0, 0 };
    double clkErr = 0;

    // 处理第一个历元
    if (spp.processEpoch(0, rxPos, clkErr)) {
        BLH blh = bdcs.XYZ2BLH(rxPos);  // 转换大地坐标
        cout << "定位结果: \n"
            << "X: " << rxPos.x << " m\n"
            << "Y: " << rxPos.y << " m\n"
            << "Z: " << rxPos.z << " m\n"
            << "B: " << blh.B << " deg\n"
            << "L: " << blh.L << " deg\n"
            << "H: " << blh.H << " m\n"
            << "钟差: " << clkErr << " m\n";
    }
    else {
        cerr << "定位失败" << endl;
    }

    return 0;
}